/*
 * Unidata Platform
 * Copyright (c) 2013-2020, UNIDATA LLC, All rights reserved.
 *
 * Commercial License
 * This version of Unidata Platform is licensed commercially and is the appropriate option for the vast majority of use cases.
 *
 * Please see the Unidata Licensing page at: https://unidata-platform.com/license/
 * For clarification or additional options, please contact: info@unidata-platform.com
 * -------
 * Disclaimer:
 * -------
 * THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND
 * REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
 * IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY,
 * FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE AND
 * THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING.
 */
package org.unidata.mdm.rest.data.service;

import java.util.UUID;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.unidata.mdm.core.util.SecurityUtils;
import org.unidata.mdm.data.service.FavoriteEtalonsService;
import org.unidata.mdm.rest.data.ro.FavoriteEtalonsRO;
import org.unidata.mdm.rest.system.ro.ErrorResponse;
import org.unidata.mdm.rest.system.ro.RestResponse;
import org.unidata.mdm.rest.system.service.AbstractRestService;
import org.unidata.mdm.system.type.runtime.MeasurementContextName;
import org.unidata.mdm.system.type.runtime.MeasurementPoint;

/**
 * @author Alexey Tsarapkin
 */
@Path("favorite-etalons")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public class FavoriteEtalonsRestService extends AbstractRestService {

    @Autowired
    private FavoriteEtalonsService favoriteEtalonsService;

    private static final String UUID_PATH_PARAM = "uuid";
    private static final String ENTITY_NAME_PATH_PARAM = "entityName";

    @GET
    @Operation(
        description = "Все любимые текущего пользователя.",
        method = HttpMethod.GET,
        responses = {
            @ApiResponse(content = @Content(schema = @Schema(implementation = RestResponse.class)), responseCode = "200"),
            @ApiResponse(content = @Content(schema = @Schema(implementation = ErrorResponse.class)), responseCode = "500")
        }
    )
    public Response getAll(@Parameter(in = ParameterIn.QUERY, description = "Имя сущности.") @QueryParam("entityName") String entityName) {
        if (StringUtils.isNoneBlank(entityName)) {
            return ok(new RestResponse<>(favoriteEtalonsService.getEtalons(entityName)));
        }

        return ok(new RestResponse<>(favoriteEtalonsService.getEtalons()));
    }

    @GET
    @Path("/etalons-map")
    @Operation(
        description = "Все любимые текущего пользователя.",
        method = HttpMethod.GET,
        responses = {
            @ApiResponse(content = @Content(schema = @Schema(implementation = RestResponse.class)), responseCode = "200"),
            @ApiResponse(content = @Content(schema = @Schema(implementation = ErrorResponse.class)), responseCode = "500")
        }
    )
    public Response getEtalonsMap(@Parameter(in = ParameterIn.QUERY, description = "Имя сущности.") @QueryParam("entityName") String entityName) {
        if (StringUtils.isNoneBlank(entityName)) {
            return ok(new RestResponse<>(favoriteEtalonsService.getEtalonsMap(entityName)));
        }

        return ok(new RestResponse<>(favoriteEtalonsService.getEtalonsMap()));
    }

    @GET
    @Path("/is-favorite/{" + UUID_PATH_PARAM + "}")
    @Operation(
        description = "Проверка в любимых или нет.",
        method = HttpMethod.GET,
        responses = {
            @ApiResponse(content = @Content(schema = @Schema(implementation = RestResponse.class)), responseCode = "200"),
            @ApiResponse(content = @Content(schema = @Schema(implementation = ErrorResponse.class)), responseCode = "500")
        }
    )
    public Response find(@Parameter(in = ParameterIn.PATH, description = "Эталон ID записи (UUID)") @PathParam(UUID_PATH_PARAM) UUID uuid) {
        return ok(new RestResponse<>(uuid != null && favoriteEtalonsService.isFavorite(uuid)));
    }

    /**
     * Add to favorites.
     *
     * @param request to save
     * @return created record
     */
    @POST
    @Operation(
        description = "Добавить в любимые.",
        method = HttpMethod.POST,
        requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = FavoriteEtalonsRO.class)), description = "Запрос"),
        responses = {
            @ApiResponse(content = @Content(schema = @Schema(implementation = RestResponse.class)), responseCode = "200"),
            @ApiResponse(content = @Content(schema = @Schema(implementation = ErrorResponse.class)), responseCode = "500")
        }
    )
    public Response add(FavoriteEtalonsRO request) {

        MeasurementPoint.init(MeasurementContextName.MEASURE_UI_CREATE);
        MeasurementPoint.start();
        try {

            if (MapUtils.isNotEmpty(request.getFavorites())) {
                favoriteEtalonsService.add(request.getFavorites());
            }

            return ok(new RestResponse<>(true));
        } finally {
            MeasurementPoint.stop();
        }
    }

    @DELETE
    @Path("/{" + UUID_PATH_PARAM + "}")
    @Operation(
        description = "Удалить из любимых по UUID.",
        method = HttpMethod.DELETE,
        responses = {
            @ApiResponse(content = @Content(schema = @Schema(implementation = RestResponse.class)), responseCode = "200"),
            @ApiResponse(content = @Content(schema = @Schema(implementation = ErrorResponse.class)), responseCode = "500")
        }
    )
    public Response deleteByUUID(@Parameter(in = ParameterIn.PATH, description = "ID записи (UUID).") @PathParam(UUID_PATH_PARAM) UUID uuid) {
        favoriteEtalonsService.exclude(uuid);
        return ok(new RestResponse<>(true));
    }

    /**
     * @param entityName
     * @return
     * @throws Exception
     */
    @DELETE
    @Path("/entity/{" + ENTITY_NAME_PATH_PARAM + "}")
    @Operation(
        description = "Удалить все из любимых по entityName.",
        method = HttpMethod.DELETE,
        responses = {
            @ApiResponse(content = @Content(schema = @Schema(implementation = RestResponse.class)), responseCode = "200"),
            @ApiResponse(content = @Content(schema = @Schema(implementation = ErrorResponse.class)), responseCode = "500")
        }
    )
    public Response deleteByEntityName(@Parameter(in = ParameterIn.PATH, description = "Имя реестра / справочника.") @PathParam(ENTITY_NAME_PATH_PARAM) String entityName) {
        favoriteEtalonsService.excludeByEntity(entityName, SecurityUtils.getCurrentUserName());
        return ok(new RestResponse<>(true));
    }

}
